import {
  View,
  FlatList,
  RefreshControl,
  StyleSheet,
  ActivityIndicator,
  Text,
  TouchableOpacity,
} from 'react-native';
import React from 'react';

interface MylistProps<T> {
  /**
   * 列表头部组件。可以直接传入一个React元素，或者一个接收数据并返回React元素的函数。
   * 如果传入函数，可以通过 `headerData` 属性为其提供数据。
   */
  HeaderComponent?: React.ReactElement | ((data?: any) => React.ReactElement);
  /**
   * 用于传递给 `HeaderComponent` 函数的数据（如果 `HeaderComponent` 是函数的话）。
   */
  headerData?: any; // 可以是任何你需要的数据结构，如对象、数组等
  DATA: T[];
  Item: React.FC<{ item: T }>;
  FOnRefresh?: () => void;
  FOnLoadMore?: () => void; // Add this line
  loadMoreFlag?: boolean;
  hasRefreshControl?: boolean; // 新增一个可选属性，默认为 true
  hasLoadMore?: boolean; // 新增一个可选属性，默认为 true
}

const Mylist = <T extends { id: string | number }>({
  HeaderComponent, // 重命名以更清晰
  headerData, // 新增头部数据属性
  DATA,
  Item,
  FOnRefresh,
  FOnLoadMore,
  loadMoreFlag,
  hasRefreshControl = true,
  hasLoadMore = true,
}: MylistProps<T>) => {
  const [refreshing, setRefreshing] = React.useState(false);
  const [loadState, setLoadState] = React.useState(LoadState.Idle);

  // 处理头部组件的渲染逻辑
  const renderHeader = () => {
    if (!HeaderComponent) return null; // 如果没有头部组件，返回 null

    // 如果 HeaderComponent 是一个函数，调用它并传入 headerData
    if (typeof HeaderComponent === 'function') {
      return HeaderComponent(headerData);
    }

    // 否则，直接返回 HeaderComponent（它已经是一个React元素）
    return HeaderComponent;
  };

  // 下拉刷新
  const onRefresh = React.useCallback(async () => {
    setRefreshing(true);
    await FOnRefresh?.();
    setRefreshing(false);
  }, []);

  // 上拉加载
  const onEndReached = React.useCallback(async () => {
    if (!hasLoadMore) return;
    if (refreshing || loadMoreFlag) {
      setLoadState(LoadState.NoMoreData);
      return setLoadState(LoadState.Idle);
    }
    // console.log(23);
    setLoadState(LoadState.Loading);
    await FOnLoadMore?.();
    setLoadState(LoadState.Idle);
  }, []);

  return (
    <View>
      <FlatList
        ListHeaderComponent={renderHeader()} // 使用我们的头部组件
        // 将DATA数据源传递给列表组件
        data={DATA}
        // 使用renderItem函数渲染每个列表项，接收一个item对象并渲染Item组件
        renderItem={({ item }) => <Item item={item} />}
        // 使用每个item的id作为列表项的唯一标识符
        keyExtractor={item => item.id.toString()}
        // 添加下拉刷新功能，refreshing控制刷新状态，onRefresh处理刷新逻辑
        refreshControl={
          <RefreshControl
            refreshing={refreshing}
            onRefresh={onRefresh}
            enabled={hasRefreshControl}
          />
        }
        // 当列表滚动到底部时触发onEndReached回调函数
        onEndReached={onEndReached}
        // 设置触发onEndReached的阈值，当距离底部还有20%的列表长度时触发
        onEndReachedThreshold={0.2}
        ListFooterComponent={
          <LoadingFooter loadState={loadState} onRefresh={onRefresh} />
        } // 使用我们的底部加载组件
      />
    </View>
  );
};

const LoadState = {
  Idle: 'Idle', // 初始态，不显示
  Loading: 'Loading', // 正在加载中
  Error: 'Error', // 加载失败，可点击重试
  NoMoreData: 'NoMoreData', // 没有更多数据了
};

const LoadingFooter = ({
  loadState,
  onRefresh,
}: {
  loadState: any;
  onRefresh: () => void;
}) => {
  switch (loadState) {
    case LoadState.Loading:
      return (
        <View style={styles.footerContainer}>
          <ActivityIndicator size="small" color="#0000ff" />
          <Text style={styles.footerText}>正在加载中...</Text>
        </View>
      );
    case LoadState.Error:
      return (
        <TouchableOpacity style={styles.footerContainer} onPress={onRefresh}>
          <Text style={[styles.footerText, { color: 'red' }]}>
            加载失败，点击重试
          </Text>
        </TouchableOpacity>
      );
    case LoadState.NoMoreData:
      return (
        <View style={styles.footerContainer}>
          <Text style={styles.footerText}>已经到底了</Text>
        </View>
      );
    case LoadState.Idle:
    default:
      return null;
  }
};

const styles = StyleSheet.create({
  footerContainer: {
    flexDirection: 'row', // 水平排列
    justifyContent: 'center', // 水平居中
    alignItems: 'center', // 垂直居中
    padding: 16,
  },
  footerText: {
    marginLeft: 8, // 给文字和指示器一点间距
    fontSize: 14,
    color: '#666',
  },
});

export default Mylist;
